// 空闲刷新模块：检测长时间未操作，提醒并刷新当前页面
// 设计要点：
// 1. 仅在设置启用时工作；支持自定义超时时间
// 2. 监听常见交互事件（键盘、鼠标、滚动、触摸），每次交互重置计时器
// 3. 超时后弹出 Element Plus 通知，并在短暂延时后刷新页面
// 4. 防重入：保证一次超时仅触发一次通知和刷新

import { ElNotification } from 'element-plus'
import { h, ref } from 'vue'
import settings from '@/settings'
import { getToken } from '@/utils/auth'
// 默认超时时间：30 分钟（仅当 settings 未配置时使用）
const DEFAULT_IDLE_MS = 30 * 60 * 1000

// 监听的用户交互事件集合
const ACTIVITY_EVENTS = ['mousemove', 'mousedown', 'keydown', 'scroll', 'touchstart', 'click']

// 管理器为单例，避免重复初始化
class IdleRefreshManager {
  // 计时器引用
  timer = null
  // 状态标记：是否已经触发过刷新
  triggered = false
  // 配置：是否启用与超时毫秒数
  enabled = true
  timeoutMs = DEFAULT_IDLE_MS
  // 通知实例与倒计时相关计时器
  notification = null
  countdownIntervalId = null
  countdownTimeoutId = null

  constructor() {
    // 从项目设置读取开关与超时
    // 关键点：读取 settings，若未定义则使用默认值，保持健壮性
    this.enabled = (settings && settings.idleRefreshEnabled) ?? true
    const cfgMs = settings && settings.idleRefreshTimeoutMs
    this.timeoutMs = typeof cfgMs === 'number' && cfgMs > 0 ? cfgMs : DEFAULT_IDLE_MS
  }

  // 初始化入口：注册事件并启动计时
  init() {
    if (!this.enabled) return
    // 关键点：防止重复初始化
    if (this.timer !== null || this.triggered) return

    if (!getToken()) return

    // 注册交互事件监听，任一事件都重置计时器
    ACTIVITY_EVENTS.forEach(evt => {
      window.addEventListener(evt, this.resetTimer, { passive: true })
    })

    // 首次启动计时
    this.startTimer()
  }

  // 启动计时器
  startTimer = () => {
    // 关键点：清理旧计时器，避免多个定时器并存
    this.clearTimer()
    this.timer = window.setTimeout(this.onIdle, this.timeoutMs)
  }

  // 重置计时器（用户活动时触发）
  resetTimer = () => {
    if (this.triggered) return // 已触发刷新后不再响应
    this.startTimer()
  }

  // 超时回调：通知并刷新页面
  onIdle = () => {
    if (this.triggered) return
    this.triggered = true
    // 关键点：显示带交互的通知，提供 10s 倒计时与“取消刷新”按钮
    this.showCountdownNotification()
  }

  // 清理计时器
  clearTimer = () => {
    if (this.timer !== null) {
      window.clearTimeout(this.timer)
      this.timer = null
    }
  }

  // 移除事件监听，释放资源
  teardown = () => {
    ACTIVITY_EVENTS.forEach(evt => {
      window.removeEventListener(evt, this.resetTimer)
    })
    this.clearTimer()
  }

  // 展示带倒计时与取消操作的通知
  showCountdownNotification = () => {
    // 倒计时秒数（要求 10s）
    const countdown = ref(10)
    // 抽取清理逻辑：关闭通知与倒计时资源，避免重复代码
    const cleanupNotification = () => {
      // 关闭通知实例
      if (this.notification) {
        this.notification.close()
        this.notification = null
      }
      // 清理每秒倒计时计时器
      if (this.countdownIntervalId) {
        window.clearInterval(this.countdownIntervalId)
        this.countdownIntervalId = null
      }
      // 清理最终刷新定时器
      if (this.countdownTimeoutId) {
        window.clearTimeout(this.countdownTimeoutId)
        this.countdownTimeoutId = null
      }
    }

    // 取消刷新：关闭通知、清理倒计时、恢复空闲检测
    const cancelRefresh = () => {
      cleanupNotification()
      // 恢复状态并重新开始空闲计时
      this.triggered = false
      this.startTimer()
    }

    // 立即刷新：关闭通知并立刻刷新页面
    const refreshNow = () => {
      // 关键点：先清理资源，避免刷新前遗留计时器
      cleanupNotification()
      // 执行页面刷新（不保留缓存状态）
      window.location.reload()
    }

    // 使用一个简单的渲染函数组件承载倒计时与交互按钮
    const CountdownContent = {
      // 渲染函数：根据 countdown 响应式值实时展示剩余秒数
      setup() {
        return () =>
          // 容器：垂直排列提示与按钮区
          h(
            'div',
            {
              style: 'display:flex; align-items:center; flex-direction:column; gap:12px; line-height:1.6; width:100%;'
            },
            [
              // 提示文案：动态展示倒计时秒数
              h('div', null, `由于长时间未操作，系统将在 ${countdown.value}s 后自动刷新。`),
              // 按钮区：横向排列“立即刷新”与“取消刷新”
              h('div', { style: 'display:flex; gap:8px; justify-content:flex-end; width:100%;' }, [
                // 立即刷新按钮（主色）
                h(
                  'button',
                  {
                    // 使用原生按钮避免引入额外组件依赖
                    style:
                      'cursor:pointer; padding:6px 10px; border:1px solid #409eff; border-radius:4px; background:#409eff; color:#fff;',
                    onClick: refreshNow
                  },
                  '立即刷新'
                ),
                // 取消刷新按钮（次级）
                h(
                  'button',
                  {
                    // 使用原生按钮避免引入额外组件依赖
                    style:
                      'cursor:pointer; padding:6px 10px; border:1px solid #dcdfe6; border-radius:4px; background:#fff; color:#606266;',
                    onClick: cancelRefresh
                  },
                  '取消刷新'
                )
              ])
            ]
          )
      }
    }

    // 弹出通知（duration: 0 表示不自动关闭，等待倒计时或用户取消）
    this.notification = ElNotification({
      title: '系统提醒',
      message: h(CountdownContent),
      type: 'warning',
      duration: 0,
      showClose: true
    })

    // 每秒递减倒计时显示
    this.countdownIntervalId = window.setInterval(() => {
      if (countdown.value <= 1) {
        window.clearInterval(this.countdownIntervalId)
        this.countdownIntervalId = null
      }
      // 关键点：提前返回，避免负数
      if (countdown.value <= 0) return
      countdown.value = countdown.value - 1
    }, 1000)

    // 到达 10s 后执行刷新
    this.countdownTimeoutId = window.setTimeout(() => {
      // 关键点：统一清理通知与倒计时资源
      cleanupNotification()
      // 执行页面刷新
      window.location.reload()
    }, 10 * 1000)
  }
}

// 单例实例
const idleRefreshManager = new IdleRefreshManager()

// 对外提供初始化方法
export function initIdleRefresh() {
  idleRefreshManager.init()
}

// 也提供销毁方法（可用于某些特殊页面禁用刷新）
export function destroyIdleRefresh() {
  idleRefreshManager.teardown()
}
